﻿using System.Windows.Input;
using CommunityToolkit.Mvvm.Input;
using Klear.Library.Models;
using Klear.Library.Services;
using Ursa.Controls;

namespace Klear.Library.ViewModels;

public class BudgetViewModel : ViewModelBase
{
    private readonly IBudgetService _budgetService;
    private readonly IRemindStorage _remindStorage;
    private readonly IContentNavigationService _contentNavigationService;
    private BudgetModel _currentBudgetModel; // 当前已保存的预算模型
    private BudgetModel _editingBudgetModel; // 正在编辑的预算模型
    private bool _isOverWarningThreshold;
    private bool _isSaving;
    private string _errorMessage;
    private bool _isLoading;
    private AsyncRelayCommand _saveBudgetSettingsCommand;
    
    public bool IsLoading
    {
        get => _isLoading;
        private set => SetProperty(ref _isLoading, value);
    }

    public BudgetViewModel(IBudgetService budgetService, 
        IRemindStorage remindStorage,
        IContentNavigationService contentnavigationService)
    {
        _budgetService = budgetService ?? throw new ArgumentNullException(nameof(budgetService));
        _remindStorage = remindStorage ?? throw new ArgumentNullException(nameof(remindStorage));
        _contentNavigationService = contentnavigationService ?? throw new ArgumentNullException(nameof(contentnavigationService));
        // 初始化两个模型，设置默认值
        _currentBudgetModel = new BudgetModel
        {
            StartDate = DateTime.Today,
            EndDate = DateTime.Today.AddMonths(1),
            Budget = 0,
            WarningThreshold = 0
        };
        _editingBudgetModel = _currentBudgetModel.Clone() as BudgetModel ?? new BudgetModel();
        
        // 注册预算警告事件
        _remindStorage.BudgetWarningTriggered += OnBudgetWarningTriggered;
        
        // 使用异步命令
        LoadBudgetSettingsCommand = new AsyncRelayCommand(LoadBudgetSettingsAsync);
        _saveBudgetSettingsCommand = new AsyncRelayCommand(SaveBudgetSettingsAsync, CanSaveBudgetSettings);
        CalculateActualSpendingCommand = new AsyncRelayCommand(CalculateActualSpendingAsync);
        CancelEditCommand = new RelayCommand(CancelEdit);
        ViewHistoryCommand = new RelayCommand(ViewHistory);

        // 注册属性变化通知
        PropertyChanged += (s, e) =>
        {
            if (e.PropertyName is nameof(IsSaving) 
                or nameof(IsLoading) 
                or nameof(EditingBudgetModel))
            {
                _saveBudgetSettingsCommand.NotifyCanExecuteChanged();
            }
        };
        
        // 初始加载预算设置
        _ = InitializeAsync();
    }
    
    public ICommand SaveBudgetSettingsCommand => _saveBudgetSettingsCommand;
    
    private async Task InitializeAsync()
    {
        try
        {
            IsLoading = true;
            await LoadBudgetSettingsAsync();
            await CalculateActualSpendingAsync();
        }
        finally
        {
            IsLoading = false;
            // 确保在初始化完成后重新评估命令状态
            _saveBudgetSettingsCommand.NotifyCanExecuteChanged();
        }
    }

    // 当前保存的预算模型（用于显示历史数据）
    public BudgetModel CurrentBudgetModel
    {
        get => _currentBudgetModel;
        private set
        {
            if (SetProperty(ref _currentBudgetModel, value))
            {
                // 当加载新的当前预算时，也更新编辑模型
                _editingBudgetModel = value.Clone() as BudgetModel ?? new BudgetModel();
                OnPropertyChanged(nameof(EditingBudgetModel));
                // 重新计算实际支出
                CalculateActualSpendingAsync().ConfigureAwait(false);
            }
        }
    }

    // 正在编辑的预算模型（用于显示和编辑新的设置）
    public BudgetModel EditingBudgetModel
    {
        get => _editingBudgetModel;
        private set
        {
            if (SetProperty(ref _editingBudgetModel, value))
            {
                _saveBudgetSettingsCommand?.NotifyCanExecuteChanged();
            }
        }
    }

    public bool IsWarningEnabled { get; set; }

    public bool IsSaving
    {
        get => _isSaving;
        private set => SetProperty(ref _isSaving, value);
    }

    public string ErrorMessage
    {
        get => _errorMessage;
        private set => SetProperty(ref _errorMessage, value);
    }

    public Task<decimal> ActualSpendingTask => 
        _budgetService.CalculateActualSpending(_currentBudgetModel.StartDate, _currentBudgetModel.EndDate);

    public bool IsOverWarningThreshold
    {
        get => _isOverWarningThreshold;
        private set => SetProperty(ref _isOverWarningThreshold, value);
    }

    public ICommand LoadBudgetSettingsCommand { get; }
    public ICommand CalculateActualSpendingCommand { get; }
    public ICommand CancelEditCommand { get; }
    public ICommand ViewHistoryCommand { get; }

    private async Task LoadBudgetSettingsAsync()
    {
        try
        {
            ErrorMessage = null;
            // 获取当前月份的预算设置
            var settings = await _budgetService.GetCurrentMonthBudgetAsync();
        
            if (settings != null)
            {
                CurrentBudgetModel = settings;
                EditingBudgetModel = settings.Clone() as BudgetModel ?? new BudgetModel();
            }
            else 
            {
                // 如果当前月份没有预算设置，则使用默认值
                var defaultModel = new BudgetModel
                {
                    StartDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1),
                    EndDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1).AddMonths(1).AddDays(-1),
                    Budget = 0,
                    WarningThreshold = 0
                };
                CurrentBudgetModel = defaultModel;
                EditingBudgetModel = defaultModel.Clone() as BudgetModel ?? new BudgetModel();
            }
            IsInitialized = true;
        }
        catch (Exception ex)
        {
            ErrorMessage = $"加载预算设置失败: {ex.Message}";
            await ShowError(ErrorMessage);
        }
    }

    private bool CanSaveBudgetSettings()
    {
        return !IsSaving && 
               !IsLoading &&
               EditingBudgetModel != null &&
               EditingBudgetModel?.Budget > 0 && 
               EditingBudgetModel?.WarningThreshold > 0 && 
               EditingBudgetModel?.StartDate < EditingBudgetModel?.EndDate;
    }

    private async Task SaveBudgetSettingsAsync()
    {
        if (IsSaving) return;

        try
        {
            IsSaving = true;
            ErrorMessage = null;

            // 验证输入
            if (!await ValidateBudgetSettings())
            {
                return;
            }

            // 保存预算设置
            await _remindStorage.UpdateBudget(EditingBudgetModel);
            
            // 更新当前预算模型
            CurrentBudgetModel = EditingBudgetModel.Clone() as BudgetModel ?? new BudgetModel();
            
            // 更新实际支出
            //await CalculateActualSpendingAsync();
            
            // 显示成功消息
            await MessageBox.ShowAsync("预算设置已成功保存");
        }
        catch (Exception ex)
        {
            ErrorMessage = $"保存预算设置失败: {ex.Message}";
            await ShowError(ErrorMessage);
        }
        finally
        {
            IsSaving = false;
        }
    }

    private void CancelEdit()
    {
        // 重置编辑中的预算模型为当前保存的值
        EditingBudgetModel = CurrentBudgetModel.Clone() as BudgetModel ?? new BudgetModel();
    }

    private async Task<bool> ValidateBudgetSettings()
    {
        if (EditingBudgetModel.Budget <= 0)
        {
            ErrorMessage = "预算金额必须大于0";
            await ShowError(ErrorMessage);
            return false;
        }

        if (EditingBudgetModel.WarningThreshold <= 0)
        {
            ErrorMessage = "预警阈值必须大于0";
            await ShowError(ErrorMessage);
            return false;
        }

        if (EditingBudgetModel.WarningThreshold >= EditingBudgetModel.Budget)
        {
            ErrorMessage = "预警阈值必须小于预算金额";
            await ShowError(ErrorMessage);
            return false;
        }

        if (EditingBudgetModel.StartDate >= EditingBudgetModel.EndDate)
        {
            ErrorMessage = "结束时间必须晚于开始时间";
            await ShowError(ErrorMessage);
            return false;
        }

        if (EditingBudgetModel.EndDate - EditingBudgetModel.StartDate < TimeSpan.FromDays(27))
        {
            ErrorMessage = "预算周期必须至少为一个月";
            await ShowError(ErrorMessage);
            return false;
        }
        
        if (EditingBudgetModel.EndDate - EditingBudgetModel.StartDate > TimeSpan.FromDays(30))
        {
            ErrorMessage = "预算周期必须至多为一个月";
            await ShowError(ErrorMessage);
            return false;
        }
        
        // 检查时间段重叠
        if (await _budgetService.HasOverlappingBudget(
                EditingBudgetModel.StartDate, 
                EditingBudgetModel.EndDate,
                EditingBudgetModel.ID))
        {
            ErrorMessage = "该时间段与现有预算时间重叠，请选择其他时间段";
            await ShowError(ErrorMessage);
            return false;
        }

        return true;
    }

    private async Task CalculateActualSpendingAsync()
    {
        try
        {
            var actualSpending = await _budgetService.CalculateActualSpending(
                CurrentBudgetModel.StartDate, 
                CurrentBudgetModel.EndDate);

            // 检查是否超过警告阈值
            IsOverWarningThreshold = actualSpending > CurrentBudgetModel.WarningThreshold;
        }
        catch (Exception ex)
        {
            ErrorMessage = $"计算实际支出失败: {ex.Message}";
            await ShowError(ErrorMessage);
        }
    }
    
    private void ViewHistory()
    {
        _contentNavigationService.NavigateTo(ContentNavigationConstant.BudgetListView);
    }

    private async void OnBudgetWarningTriggered(object sender, BudgetWarningEventArgs e)
    {
        IsOverWarningThreshold = true;
    }

    private async Task ShowError(string message)
    {
        await MessageBox.ShowAsync(message, "错误");
    }

    public override void Cleanup()
    {
        _remindStorage.BudgetWarningTriggered -= OnBudgetWarningTriggered;
        base.Cleanup();
    }

    public override void SetParameter(object parameter)
    {
        if (parameter is BudgetModel budgetModel)
        {
            CurrentBudgetModel = budgetModel;
        }
    }
}